home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / programm.ing / ams__l~1.zoo / src / sprite.cc < prev    next >
Encoding:
C/C++ Source or Header  |  1993-09-05  |  28.9 KB  |  1,604 lines

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. //  This file is part of the Atari Machine Specific Library,
  4. //  and is Copyright 1992 by Warwick W. Allison.
  5. //
  6. //  You are free to copy and modify these sources, provided you acknowledge
  7. //  the origin by retaining this notice, and adhere to the conditions
  8. //  described in the file COPYING.
  9. //
  10. //////////////////////////////////////////////////////////////////////////////
  11.  
  12. //  I/O return values need work.  Sorry - hacky 'game' mentality.
  13.  
  14. #ifndef __OPTIMIZE__
  15. // Still with GCC 2.3.3 (and it actually detects it now)
  16. #error "Due to register restrictions, this file must be optimized (-O)"
  17. #endif
  18.  
  19.  
  20. #include "Sprite.h"
  21. #include "DoubleBuffer.h"
  22.  
  23. Incarnation::Incarnation(short h, int b) :
  24.     height(h), Backing(b),
  25.     HotX(0), HotY(0)
  26. { }
  27.  
  28. void Incarnation::SetHotSpot(short x, short y)
  29. {
  30.     HotX=x;
  31.     HotY=y;
  32. }
  33.  
  34. void Sprite::Draw()
  35. {
  36.     long* Back=BackingStore[Pages->Pulse];
  37.     *Back++=(long)Inca[shape];
  38.     Inca[shape]->Draw(x >> Shift,y >> Shift,Back);
  39. }
  40.  
  41. int Sprite::TouchDraw()
  42. {
  43.     long* Back=BackingStore[Pages->Pulse];
  44.     *Back++=(long)Inca[shape];
  45.     return Inca[shape]->TouchDraw(x >> Shift,y >> Shift,Back);
  46. }
  47.  
  48. void Sprite::Wipe()
  49. {
  50.     long *Back=BackingStore[Pages->Pulse];
  51.     Incarnation* OldInca=(Incarnation*)*Back;
  52.     if (OldInca) {
  53.         *Back++=0;
  54.         OldInca->Wipe(Back);
  55.     }
  56. }
  57.  
  58. short LeftBits(unsigned short x)
  59. {
  60.     for (int i=0; x; x<<=1) i++;
  61.     return i;
  62. }
  63.  
  64. short LongLeftBits(unsigned long x)
  65. {
  66.     for (int i=0; x; x<<=1) i++;
  67.     return i;
  68. }
  69.  
  70. Sprite::Sprite(Sprite& Copy)
  71. {
  72.     *this=Copy;
  73.  
  74.     BackingStore[0]=new long[BackingSize];
  75.     BackingStore[1]=new long[BackingSize];
  76.     BackingStore[0][0]=0;
  77.     BackingStore[1][0]=0;
  78.  
  79.     ExternalInca=TRUE;
  80. }
  81.  
  82. Sprite::Sprite(Incarnation **List,int Count) :
  83.     x(50),
  84.     y(50),
  85.     shape(0),
  86.     BackingSize(2),
  87.     OverlayMask(0),
  88.     ExternalInca(TRUE),
  89.     Shift(0)
  90. {
  91.     for (int i=0; i<Count; i++) {
  92.         if (List[i]->BackingRequired() > BackingSize)
  93.             BackingSize=List[i]->BackingRequired();
  94.     }
  95.     BackingSize++; // For OldInca
  96.     BackingStore[0]=new long[BackingSize];
  97.     BackingStore[1]=new long[BackingSize];
  98.     BackingStore[0][0]=0;
  99.     BackingStore[1][0]=0;
  100.  
  101.     MaxInca=Count;
  102.     Inca=List;
  103. }
  104.  
  105. Sprite::Sprite(Incarnation *OnlyOne) :
  106.     x(50),
  107.     y(50),
  108.     shape(0),
  109.     BackingSize(OnlyOne->BackingRequired()+1),
  110.     OverlayMask(0),
  111.     ExternalInca(FALSE),
  112.     MaxInca(1),
  113.     Shift(0)
  114. {
  115.     BackingStore[0]=new long[BackingSize];
  116.     BackingStore[1]=new long[BackingSize];
  117.     BackingStore[0][0]=0;
  118.     BackingStore[1][0]=0;
  119.  
  120.     Inca=new Incarnation*[1];
  121.  
  122.     Inca[0]=OnlyOne;
  123. }
  124.  
  125. Sprite::Sprite(FILE *fp) :
  126.     Inca(0)
  127. {
  128.     if (!fget(fp)) {
  129.         // ?
  130.     }
  131. }
  132.  
  133. Sprite::Sprite(const char *filename) :
  134.     Inca(0)
  135. {
  136.     FILE* fp=fopen(filename,"rb");
  137.     fget(fp);
  138.     if (!fclose(fp)) {
  139.         // ?
  140.     }
  141. }
  142.  
  143. Sprite::Sprite(short maxinca) :
  144.     x(50),
  145.     y(50),
  146.     shape(0),
  147.     BackingSize(2), // Nothing really
  148.     Shift(0),
  149.     OverlayMask(0),
  150.     MaxInca(maxinca),
  151.     Inca(new Incarnation*[MaxInca]),
  152.     ExternalInca(FALSE)
  153. {
  154.     BackingStore[0]=new long[BackingSize];
  155.     BackingStore[1]=new long[BackingSize];
  156.     BackingStore[0][0]=0;
  157.     BackingStore[1][0]=0;
  158.  
  159.     for (int i=0; i<MaxInca; i++) Inca[i]=0;
  160. }
  161.  
  162. Sprite::~Sprite()
  163. {
  164.     delete BackingStore[0];
  165.     delete BackingStore[1];
  166.     if (!ExternalInca) {
  167.         for (int i=0; i<MaxInca; i++) if (Inca[i]) delete Inca[i];
  168.         delete Inca;
  169.     }
  170. }
  171.  
  172. void    Sprite::SetImage(int i, Incarnation* In)
  173. {
  174.     if (BackingSize < In->BackingRequired()+1) {
  175.         BackingSize=In->BackingRequired()+1;
  176.         delete BackingStore[0];
  177.         delete BackingStore[1];
  178.         BackingStore[0]=new long[BackingSize];
  179.         BackingStore[1]=new long[BackingSize];
  180.         BackingStore[0][0]=0;
  181.         BackingStore[1][0]=0;
  182.     }
  183.     Inca[i]=In;
  184. }
  185.  
  186. #define READ(x) fread(&x,sizeof(x),1,fp)
  187. #define WRITE(x) fwrite(&x,sizeof(x),1,fp)
  188.  
  189. Incarnation* IncarnationReader(FILE *fp)
  190. {
  191.     short Tag;
  192.  
  193.     fread(&Tag,sizeof(Tag),1,fp);
  194.  
  195.     switch (Tag) {
  196.      case 0:
  197.         return new MonochromeIncarnation(fp);
  198.     break; case 1:
  199.         return new ColourIncarnation(fp);
  200.     break; case 2:
  201.         return new WideMonochromeIncarnation(fp);
  202.     break; case 3:
  203.         return new WideColourIncarnation(fp);
  204.     break; case 4:
  205.         return new PreshiftedMonochromeIncarnation(fp);
  206.     break; case 5:
  207.         return new PreshiftedColourIncarnation(fp);
  208.     break; case 6:
  209.         return new TrueColourIncarnation(fp);
  210.     break; default:
  211.         return 0;
  212.     }
  213. }
  214.  
  215. int    Sprite::fget(FILE *fp)
  216. {
  217.     fread(&x,sizeof(x),1,fp);
  218.     fread(&y,sizeof(y),1,fp);
  219.     fread(&shape,sizeof(shape),1,fp);
  220.     fread(&Shift,sizeof(Shift),1,fp);
  221.  
  222.     if (Inca && !ExternalInca) {
  223.         for (int i=0; i<MaxInca; i++) if (Inca[i]) delete Inca[i];
  224.         delete Inca;
  225.     }
  226.  
  227.     fread(&MaxInca,sizeof(MaxInca),1,fp);
  228.  
  229.     Inca=new Incarnation*[MaxInca];
  230.  
  231.     int i;
  232.  
  233.     for (i=0; i<MaxInca; i++) {
  234.         short yes;
  235.         READ(yes);
  236.         if (yes) {
  237.             Inca[i]=IncarnationReader(fp);
  238.         } else {
  239.             Inca[i]=0;
  240.         }
  241.     }
  242.  
  243.     BackingSize=2; // Nothing really
  244.     for (i=0; i<MaxInca; i++) {
  245.         if (Inca[i] && Inca[i]->BackingRequired() > BackingSize)
  246.             BackingSize=Inca[i]->BackingRequired();
  247.     }
  248.     BackingSize++; // For OldInca
  249.     BackingStore[0]=new long[BackingSize];
  250.     BackingStore[1]=new long[BackingSize];
  251.     BackingStore[0][0]=0;
  252.     BackingStore[1][0]=0;
  253.  
  254.     ExternalInca=FALSE;
  255.  
  256.     return 1;
  257. }
  258.  
  259. int    Sprite::fput(FILE *fp)
  260. {
  261.     fwrite(&x,sizeof(x),1,fp);
  262.     fwrite(&y,sizeof(y),1,fp);
  263.     fwrite(&shape,sizeof(shape),1,fp);
  264.     fwrite(&Shift,sizeof(Shift),1,fp);
  265.     fwrite(&MaxInca,sizeof(MaxInca),1,fp);
  266.  
  267.     for (int i=0; i<MaxInca; i++) {
  268.         short yes=(Inca[i]!=0);
  269.         fwrite(&yes,sizeof(yes),1,fp);
  270.         if (yes) Inca[i]->fput(fp);
  271.     }
  272.  
  273.     return 1;
  274. }
  275.  
  276. int    Sprite::Load(const char *filename)
  277. {
  278.     FILE* fp=fopen(filename,"rb");
  279.     if (!fp) return 0;
  280.     fget(fp);
  281.     return fclose(fp);
  282. }
  283.  
  284. int    Sprite::Save(const char *filename)
  285. {
  286.     FILE* fp=fopen(filename,"wb");
  287.     if (!fp) return 0;
  288.     fput(fp);
  289.     return fclose(fp);
  290. }
  291.  
  292. MonochromeIncarnation::MonochromeIncarnation(int h) :
  293.     Incarnation(h,h+2),
  294.     Data(new unsigned short[h]),
  295.     Mask(new unsigned short[h])
  296. {
  297. }
  298.  
  299. MonochromeIncarnation::~MonochromeIncarnation()
  300. {
  301.     delete Data;
  302.     delete Mask;
  303. }
  304.  
  305. int    Incarnation::fput(FILE *fp)
  306. {
  307.     fwrite(&width,sizeof(width),1,fp);
  308.     fwrite(&height,sizeof(height),1,fp);
  309.     fwrite(&HotX,sizeof(HotX),1,fp);
  310.     return (fwrite(&HotY,sizeof(HotY),1,fp)==1);
  311. }
  312.  
  313. Incarnation::Incarnation(FILE *fp)
  314. {
  315.     READ(width);
  316.     READ(height);
  317.     READ(HotX);
  318.     READ(HotY);
  319. }
  320.  
  321. int    MonochromeIncarnation::fput(FILE *fp)
  322. {
  323.     short tag=0;
  324.     fwrite(&tag,sizeof(tag),1,fp);
  325.     Incarnation::fput(fp);
  326.     fwrite(Data,sizeof(*Data),height,fp);
  327.     return (fwrite(Mask,sizeof(*Mask),height,fp)==height);
  328. }
  329.  
  330. MonochromeIncarnation::MonochromeIncarnation(FILE *fp) :
  331.     Incarnation(fp),
  332.     Data(new unsigned short[height]),
  333.     Mask(new unsigned short[height])
  334. {
  335.     Backing=height+2;
  336.     fread(Data,sizeof(*Data),height,fp);
  337.     fread(Mask,sizeof(*Mask),height,fp);
  338. }
  339.  
  340.  
  341. int    MonochromeIncarnation::TouchDraw(short x, short y, long *Store)
  342. { return 0; }
  343.  
  344. void    MonochromeIncarnation::Draw(short x, short y, long *Store)
  345. {
  346.     x-=HotX;
  347.     y-=HotY;
  348.     short LineSpacing=Pages->Current().Rez().BytesPerLine();
  349.     long *At = (long*)(Pages->Location() + y*LineSpacing + ((x>>4)<<1));
  350.     unsigned short shift = 16-(x&15);
  351. #ifdef NOASM
  352.     unsigned short *D=Data;
  353.     unsigned short *M=Mask;
  354.  
  355.     *(Store++)=(long)At;
  356.     *(Store++)=(long)height-1;
  357.     for (int h=0; h<height; h++) {
  358.         *(Store++)=*At;
  359.         *At=(*At & ~((long)(*(M++)) << shift)) | ((long)(*(D++)) << shift);
  360.         At=(long*)((long)At+LineSpacing);
  361.     }
  362. #else
  363.     asm("
  364.             subl    #1,%6
  365.             movel    %0,%5@+
  366.             movel    %6,%5@+
  367.         0:    movel    %0@,d0
  368.             movel    d0,%5@+
  369.             clrl    d1
  370.             movew    %1@+,d1
  371.             asll    %3,d1
  372.             notl    d1
  373.             andl    d1,d0
  374.             clrl    d1
  375.             movew    %2@+,d1
  376.             asll    %3,d1
  377.             orl    d1,d0
  378.             movel    d0,%0@
  379.             addl    %4,%0
  380.             dbra    %6,0b
  381.         1:
  382.     "    : 
  383.         : "a" (At),
  384.           "a" (Mask),
  385.           "a" (Data),
  386.           "d" (shift),
  387.           "d" ((long)LineSpacing),
  388.           "a" (Store),
  389.           "d" (height)
  390.         
  391.         : "d0", "d1");
  392. #endif
  393. }
  394.  
  395. void    SimpleMonoWipe(long *Store)
  396. {
  397.     short LineSpacing=Pages->Current().Rez().BytesPerLine();
  398. #ifdef NOASM
  399.     if (*Store) {
  400.         long *At = (long*)*Store;
  401.         *(Store++) = 0;
  402.  
  403.         for (int h=1+*(Store++); h; h--) {
  404.             *At=*(Store++);
  405.             At=(long*)((long)At+LineSpacing);
  406.         }
  407.     }
  408. #else
  409.     asm("
  410.     movel    %0@,d0        | Since moves to address regs don't change Z flag
  411.     beq    1f
  412.     movel    d0,a0
  413.     clrl    %0@+
  414.     movel    %0@+,d0
  415. 0:
  416.     movel    %0@+,a0@
  417.     addl    %1,a0        | next line on screen
  418.     dbra    d0,0b
  419. 1:
  420. " :
  421.   :    "a" (Store),
  422.     "d" ((long)LineSpacing)
  423.  
  424.   :    "d0", "a0"
  425. );
  426. #endif
  427. }
  428.  
  429. void    MonochromeIncarnation::Wipe(long *Store)
  430. {
  431.     SimpleMonoWipe(Store);
  432. }
  433.  
  434. void    MonochromeIncarnation::GetImage(Screen& S, int x, int y)
  435. {
  436.     short LineSpacing=S.Rez().BytesPerLine();
  437.     unsigned short *At=(unsigned short*)(S.Location()+y*LineSpacing+x/16*2);
  438.     unsigned short *D,*M;
  439.     unsigned short or=0;
  440.  
  441.     D=Data;
  442.     M=Mask;
  443.     for (int h=0; h<height; h++) {
  444.         *D++=At[0];
  445.         *M++=At[1];
  446.         or|=At[1];
  447.         At=(unsigned short*)((long)At+LineSpacing);
  448.     }
  449.  
  450.     width=LeftBits(or);
  451. }
  452.  
  453.  
  454. WideMonochromeIncarnation::WideMonochromeIncarnation(int h) :
  455.     Incarnation(h,(h+1)*3/2+2),
  456.     Data(new unsigned long[h]),
  457.     Mask(new unsigned long[h])
  458. { }
  459.  
  460. WideMonochromeIncarnation::~WideMonochromeIncarnation()
  461. {
  462.     delete Data;
  463.     delete Mask;
  464. }
  465.  
  466. int    WideMonochromeIncarnation::fput(FILE *fp)
  467. {
  468.     short tag=2;
  469.     fwrite(&tag,sizeof(tag),1,fp);
  470.     Incarnation::fput(fp);
  471.     fwrite(Data,sizeof(*Data),height,fp);
  472.     return fwrite(Mask,sizeof(*Mask),height,fp)==height;
  473. }
  474.  
  475. WideMonochromeIncarnation::WideMonochromeIncarnation(FILE *fp) :
  476.     Incarnation(fp),
  477.     Data(new unsigned long[height]),
  478.     Mask(new unsigned long[height])
  479. {
  480.     Backing=(height+1)*3/2+2;
  481.     fread(Data,sizeof(*Data),height,fp);
  482.     fread(Mask,sizeof(*Mask),height,fp);
  483. }
  484.  
  485.  
  486.  
  487. int    WideMonochromeIncarnation::TouchDraw(short x, short y, long *Store)
  488. { return 0; }
  489.  
  490. void    WideMonochromeIncarnation::Draw(short x, short y, long *Store)
  491. {
  492.     x-=HotX;
  493.     y-=HotY;
  494.     short LineSpacing=Pages->Current().Rez().BytesPerLine();
  495.     long *At = (long*)(Pages->Location() + y*LineSpacing + x/16*2);
  496. #ifdef NOASM
  497.     error("This is too hard to do without assembler");
  498. #else
  499.     short rshift=x&15;
  500.     short lshift=16-rshift;
  501.  
  502.     asm("
  503.     movel    %5,%2@+        | Save output address
  504.     subl    #1,%6
  505.     movel    %6,%2@+        | Save Height-1
  506. 0:
  507. |    Save scanline:
  508.     movel    %5@,%2@+
  509.     movew    %5@(4),%2@+
  510.  
  511. |    Get mask
  512.     movel    %1@+,d3
  513.     movew    d3,d4
  514.     lsrl    %4,d3
  515.     aslw    %3,d4
  516.     notl    d3
  517.     notw    d4
  518.  
  519. |    Draw scanline:
  520.     movel    %0@+,d1
  521.     movew    d1,d2
  522.     lsrl    %4,d1
  523.     aslw    %3,d2
  524.  
  525.     movew    %5@(4),d0    | First the right end word
  526.     andw    d4,d0
  527.     orw    d2,d0
  528.     movew    d0,%5@(4)
  529.     movel    %5@,d0        | Then the left end long
  530.     andl    d3,d0
  531.     orl    d1,d0
  532.     movel    d0,%5@
  533.     
  534.     addl    %7,%5        | next line on screen
  535.  
  536.     dbra    %6,0b
  537.  
  538. " :
  539.   :    "a" (Data),
  540.     "a" (Mask),
  541.     "a" (Store),
  542.     "d" (lshift),
  543.     "d" (rshift),
  544.     "a" (At),
  545.     "d" ((long)height),
  546.     "a" ((long)LineSpacing)
  547.  
  548.   :    "d0", "d1", "d2", "d3", "d4"
  549. );
  550. #endif
  551. }
  552.  
  553. void    WideMonochromeIncarnation::Wipe(long *Store)
  554. {
  555.     short LineSpacing=Pages->Current().Rez().BytesPerLine();
  556. #ifdef NOASM
  557.     error("Too hairy mixing long and short without ASM");
  558. #else
  559.     asm("
  560.     movel    %0@,d0        | Since moves to address regs don't change Z flag
  561.     beq    1f
  562.     movel    d0,a0
  563.     clrl    %0@+
  564.     movel    %0@+,d0
  565.     subl    #4,%1
  566. 0:
  567.     movel    %0@+,a0@+
  568.     movew    %0@+,a0@
  569.     addl    %1,a0        | next line on screen
  570.     dbra    d0,0b
  571. 1:
  572. " :
  573.   :    "a" (Store),
  574.     "d" ((long)LineSpacing)
  575.  
  576.   :    "d0", "a0"
  577. );
  578. #endif
  579. }
  580.  
  581. void    WideMonochromeIncarnation::GetImage(Screen& S, int x, int y)
  582. {
  583.     short LineSpacing=S.Rez().BytesPerLine();
  584.     unsigned long *At=(unsigned long*)(S.Location()+y*LineSpacing+x/16*2);
  585.     unsigned long or=0,*D,*M;
  586.  
  587.     D=Data;
  588.     M=Mask;
  589.     for (int h=0; h<height; h++) {
  590.         *D=*At;
  591.         *M=At[1];
  592.         or|=*M++;
  593.         D++;
  594.         At=(unsigned long*)((long)At+LineSpacing);
  595.     }
  596.     width=LongLeftBits(or);
  597. }
  598.  
  599.  
  600.  
  601. PreshiftedMonochromeIncarnation::PreshiftedMonochromeIncarnation(int h)
  602.     : Incarnation(h,h+2)
  603. {
  604.     int s;
  605.  
  606.     for (s=0; s<16; s++) Data[s]=new unsigned long[height];
  607.     for (s=0; s<16; s++) Mask[s]=new unsigned long[height];
  608. }
  609.  
  610. PreshiftedMonochromeIncarnation::~PreshiftedMonochromeIncarnation()
  611. {
  612.     int s;
  613.  
  614.     for (s=0; s<16; s++) delete Data[s];
  615.     for (s=0; s<16; s++) delete Mask[s];
  616. }
  617.  
  618. int    PreshiftedMonochromeIncarnation::fput(FILE *fp)
  619. {
  620.     short tag=4;
  621.     fwrite(&tag,sizeof(tag),1,fp);
  622.     Incarnation::fput(fp);
  623.     fwrite(Data[0],sizeof(*Data[0]),height,fp);
  624.     return fwrite(Mask[0],sizeof(*Mask[0]),height,fp)==height;
  625. }
  626.  
  627. PreshiftedMonochromeIncarnation::PreshiftedMonochromeIncarnation(FILE *fp) :
  628.     Incarnation(fp)
  629. {
  630.     int s;
  631.  
  632.     for (s=0; s<16; s++) Data[s]=new unsigned long[height];
  633.     for (s=0; s<16; s++) Mask[s]=new unsigned long[height];
  634.  
  635.     Backing=height+2;
  636.     fread(Data[0],sizeof(*Data[0]),height,fp);
  637.     fread(Mask[0],sizeof(*Mask[0]),height,fp);
  638.  
  639.     // **** BELOW COPIED FROM GetImage - should be private member.
  640.     unsigned long *D,*M,*SD,*SM;
  641.  
  642.     for (s=1; s<16; s++) {
  643.         D=Data[0];
  644.         M=Mask[0];
  645.  
  646.         SD=Data[s];
  647.         SM=Mask[s];
  648.  
  649.         for (int h=0; h<height; h++) {
  650.             *SD++=*D++>>s;
  651.             *SM++=~(*M++>>s);
  652.         }
  653.     }
  654.  
  655.     M=Mask[0];
  656.     for (int h=0; h<height; h++) {
  657.         M[h]=~M[h];
  658.     }
  659.     // **** ABOVE COPIED FROM GetImage - should be private member.
  660. }
  661.  
  662.  
  663. int    PreshiftedMonochromeIncarnation::TouchDraw(short x, short y, long *Store)
  664. { return 0; }
  665.  
  666. void    PreshiftedMonochromeIncarnation::Draw(short x, short y, long *Store)
  667. {
  668.     x-=HotX;
  669.     y-=HotY;
  670.     unsigned short shift = x&15;
  671.     short LineSpacing=Pages->Current().Rez().BytesPerLine();
  672.     long *At = (long*)(Pages->Location() + y*LineSpacing+((x>>4)<<1));
  673. #ifdef NOASM
  674.     unsigned long *D=Data[shift];
  675.     unsigned long *M=Mask[shift];
  676.  
  677.     unsigned long m;
  678.  
  679.     *(Store++)=(long)At;
  680.     *(Store++)=(long)height-1;
  681.     for (int h=0; h<height; h++) {
  682.         m=*(M++);
  683.  
  684.         *(Store++)=*At;
  685.  
  686.         *At=*At & m | *(D++);
  687.  
  688.         At=(long*)((long)At+LineSpacing);
  689.     }
  690. #else
  691.     asm("
  692.     movel    %2,%3@+        | Save output address
  693.     subl    #1,%4
  694.     movel    %4,%3@+        | Save Height-1
  695. 0:
  696. |    Get mask
  697.     movel    %0@+,d1
  698.  
  699.     movel    %1@+,d0
  700.     movel    %2@,d4
  701.     movel    d4,%3@+
  702.     andl    d1,d4
  703.     orl    d0,d4
  704.     movel    d4,%2@
  705.  
  706.     addl    %5,%2    | next line on screen
  707.  
  708.     dbra    %4,0b
  709. " :
  710.   :    "a" (Mask[shift]),
  711.     "a" (Data[shift]),
  712.     "a" (At),
  713.     "a" (Store),
  714.     "d" (height),
  715.     "d" ((long)LineSpacing)
  716.   :    "d0", "d1", "d4"
  717. );
  718. #endif
  719. }
  720.  
  721. void    PreshiftedMonochromeIncarnation::Wipe(long *Store)
  722. {
  723.     SimpleMonoWipe(Store);
  724. }
  725.  
  726.  
  727. void    PreshiftedMonochromeIncarnation::GetImage(Screen& S, int x, int y)
  728. {
  729.     short LineSpacing=S.Rez().BytesPerLine();
  730.     unsigned short *At=(unsigned short*)(S.Location()+y*LineSpacing+x/16*2);
  731.     unsigned long *D,*M,*SD,*SM;
  732.     unsigned short or=0;
  733.     int h;
  734.  
  735.     D=Data[0];
  736.     M=Mask[0];
  737.     for (h=0; h<height; h++) {
  738.         *D++=At[0] << 16;
  739.         *M++=At[1] << 16;
  740.         or|=At[1];
  741.         At=(unsigned short*)((long)At+LineSpacing);
  742.     }
  743.     width=LeftBits(or);
  744.  
  745.     for (int s=1; s<16; s++) {
  746.         D=Data[0];
  747.         M=Mask[0];
  748.  
  749.         SD=Data[s];
  750.         SM=Mask[s];
  751.  
  752.         for (h=0; h<height; h++) {
  753.             *SD++=*D++>>s;
  754.  
  755.             *SM++=~(*M++>>s);
  756.         }
  757.     }
  758.  
  759.     M=Mask[0];
  760.     for (h=0; h<height; h++) {
  761.         M[h]=~M[h];
  762.     }
  763. }
  764.  
  765.  
  766. WideColourIncarnation::WideColourIncarnation(int h) :
  767.     Incarnation(h,h*6+2),
  768.     Data(new unsigned long[h*4]),
  769.     Mask(new unsigned long[h])
  770. { }
  771.  
  772. WideColourIncarnation::~WideColourIncarnation()
  773. {
  774.     delete Data;
  775.     delete Mask;
  776. }
  777.  
  778. int    WideColourIncarnation::fput(FILE *fp)
  779. {
  780.     short tag=3;
  781.     fwrite(&tag,sizeof(tag),1,fp);
  782.     Incarnation::fput(fp);
  783.     fwrite(Data,sizeof(*Data),height*6,fp);
  784.     return fwrite(Mask,sizeof(*Mask),height,fp)==height;
  785. }
  786.  
  787. WideColourIncarnation::WideColourIncarnation(FILE *fp) :
  788.     Incarnation(fp),
  789.     Data(new unsigned long[height*6]),
  790.     Mask(new unsigned long[height])
  791. {
  792.     Backing=height*6+2;
  793.     fread(Data,sizeof(*Data),height*6,fp);
  794.     fread(Mask,sizeof(*Mask),height,fp);
  795. }
  796.  
  797.  
  798. int    WideColourIncarnation::TouchDraw(short x, short y, long *Store)
  799. { return 0; }
  800.  
  801. void    WideColourIncarnation::Draw(short x, short y, long *Store)
  802. {
  803.     x-=HotX;
  804.     y-=HotY;
  805.     short LineSpacing=Pages->Current().Rez().BytesPerLine();
  806.     long *At = (long*)(Pages->Location() + y*LineSpacing+((x>>4)<<3));
  807. #ifdef NOASM
  808.     error("This is too hard to do without assembler");
  809. #else
  810.     short rshift=x&15;
  811.     short lshift=16-rshift;
  812.  
  813.     asm("
  814.     movel    %5,%2@+        | Save output address
  815.     subl    #1,%6
  816.     movel    %6,%2@+        | Save Height-1
  817. 0:
  818. |    Save scanline:
  819.     movel    %5@,%2@+
  820.     movel    %5@(4),%2@+
  821.     movel    %5@(8),%2@+
  822.     movel    %5@(12),%2@+
  823.     movel    %5@(16),%2@+
  824.     movel    %5@(20),%2@+
  825.  
  826. |    Get mask
  827.     movel    %1@+,d3
  828.     movew    d3,d4
  829.     lsrl    %4,d3
  830.     aslw    %3,d4
  831.     notl    d3
  832.     notw    d4
  833.  
  834. |    Draw scanline:
  835.     movel    %0@+,d1
  836.     movew    d1,d2
  837.     lsrl    %4,d1
  838.     aslw    %3,d2
  839.  
  840.     movew    %5@(16),d0    | First the right end word
  841.     andw    d4,d0
  842.     orw    d2,d0
  843.     movew    d0,%5@(16)
  844.     movew    %5@,d0        | Then the left end long
  845.     swap    d0
  846.     movew    %5@(8),d0
  847.     andl    d3,d0
  848.     orl    d1,d0
  849.     movew    d0,%5@(8)
  850.     swap    d0
  851.     movew    d0,%5@+
  852.     
  853. |    Draw scanline:
  854.     movel    %0@+,d1
  855.     movew    d1,d2
  856.     lsrl    %4,d1
  857.     aslw    %3,d2
  858.  
  859.     movew    %5@(16),d0    | First the right end word
  860.     andw    d4,d0
  861.     orw    d2,d0
  862.     movew    d0,%5@(16)
  863.     movew    %5@,d0        | Then the left end long
  864.     swap    d0
  865.     movew    %5@(8),d0
  866.     andl    d3,d0
  867.     orl    d1,d0
  868.     movew    d0,%5@(8)
  869.     swap    d0
  870.     movew    d0,%5@+
  871.     
  872. |    Draw scanline:
  873.     movel    %0@+,d1
  874.     movew    d1,d2
  875.     lsrl    %4,d1
  876.     aslw    %3,d2
  877.  
  878.     movew    %5@(16),d0    | First the right end word
  879.     andw    d4,d0
  880.     orw    d2,d0
  881.     movew    d0,%5@(16)
  882.     movew    %5@,d0        | Then the left end long
  883.     swap    d0
  884.     movew    %5@(8),d0
  885.     andl    d3,d0
  886.     orl    d1,d0
  887.     movew    d0,%5@(8)
  888.     swap    d0
  889.     movew    d0,%5@+
  890.     
  891. |    Draw scanline:
  892.     movel    %0@+,d1
  893.     movew    d1,d2
  894.     lsrl    %4,d1
  895.     aslw    %3,d2
  896.  
  897.     movew    %5@(16),d0    | First the right end word
  898.     andw    d4,d0
  899.     orw    d2,d0
  900.     movew    d0,%5@(16)
  901.     movew    %5@,d0        | Then the left end long
  902.     swap    d0
  903.     movew    %5@(8),d0
  904.     andl    d3,d0
  905.     orl    d1,d0
  906.     movew    d0,%5@(8)
  907.     swap    d0
  908.     movew    d0,%5@+
  909.     
  910.     addl    %7,%5        | next line on screen
  911.     subl    #8,%5
  912.  
  913.     dbra    %6,0b
  914.  
  915. " :
  916.   :    "a" (Data),
  917.     "a" (Mask),
  918.     "a" (Store),
  919.     "d" (lshift),
  920.     "d" (rshift),
  921.     "a" (At),
  922.     "d" ((long)height),
  923.     "a" ((long)LineSpacing)
  924.  
  925.   :    "d0", "d1", "d2", "d3", "d4"
  926. );
  927. #endif
  928. }
  929.  
  930. void    WideColourIncarnation::Wipe(long *Store)
  931. {
  932.     short LineSpacing=Pages->Current().Rez().BytesPerLine();
  933. #ifdef NOASM
  934.     if (*Store) {
  935.         long *At = (long*) *Store;
  936.         *(Store++) = 0;
  937.  
  938.         for (int h=1+*(Store++); h; h--) {
  939.             *At=*(Store++);
  940.             At[1]=*(Store++);
  941.             At[2]=*(Store++);
  942.             At[3]=*(Store++);
  943.             At[4]=*(Store++);
  944.             At[5]=*(Store++);
  945.             At=(long*)((long)At+LineSpacing);
  946.         }
  947.     }
  948. #else
  949.     asm("
  950.     movel    %0@,d0        | Since moves to address regs don't change Z flag
  951.     beq    1f
  952.     movel    d0,a0
  953.     clrl    %0@+
  954.     movel    %0@+,d0
  955.     subl    #20,%1
  956. 0:
  957.     movel    %0@+,a0@+
  958.     movel    %0@+,a0@+
  959.     movel    %0@+,a0@+
  960.     movel    %0@+,a0@+
  961.     movel    %0@+,a0@+
  962.     movel    %0@+,a0@
  963.     addl    %1,a0        | next line on screen
  964.     dbra    d0,0b
  965. 1:
  966. " :
  967.   :    "a" (Store),
  968.     "d" ((long)LineSpacing)
  969.  
  970.   :    "d0", "a0"
  971. );
  972. #endif
  973. }
  974.  
  975. void    WideColourIncarnation::GetImage(Screen& S, int x, int y)
  976. {
  977.     short LineSpacing=S.Rez().BytesPerLine();
  978.     unsigned short *At=(unsigned short*)(S.Location()+y*LineSpacing+x/16*8);
  979.     unsigned long or=0,*D,*M;
  980.  
  981.     D=Data;
  982.     M=Mask;
  983.     for (int h=0; h<height; h++) {
  984.         D[0]=At[0]<<16|At[4];
  985.         D[1]=At[1]<<16|At[5];
  986.         D[2]=At[2]<<16|At[6];
  987.         D[3]=At[3]<<16|At[7];
  988.         *M=D[0]|D[1]|D[2]|D[3];
  989.         or|=*M++;
  990.         D+=4;
  991.         At=(unsigned short*)((long)At+LineSpacing);
  992.     }
  993.     width=LongLeftBits(or);
  994. }
  995.  
  996.  
  997.  
  998. ColourIncarnation::ColourIncarnation(int h) :
  999.     Incarnation(h,h*4+2),
  1000.     Data(new unsigned short[h*4]),
  1001.     Mask(new unsigned short[h])
  1002. { }
  1003.  
  1004. ColourIncarnation::~ColourIncarnation()
  1005. {
  1006.     delete Data;
  1007.     delete Mask;
  1008. }
  1009.  
  1010. int    ColourIncarnation::fput(FILE *fp)
  1011. {
  1012.     short tag=1;
  1013.     fwrite(&tag,sizeof(tag),1,fp);
  1014.     Incarnation::fput(fp);
  1015.     fwrite(Data,sizeof(*Data),height*4,fp);
  1016.     return fwrite(Mask,sizeof(*Mask),height,fp)==height;
  1017. }
  1018.  
  1019. ColourIncarnation::ColourIncarnation(FILE *fp) :
  1020.     Incarnation(fp),
  1021.     Data(new unsigned short[height*4]),
  1022.     Mask(new unsigned short[height])
  1023. {
  1024.     Backing=height*4+2;
  1025.     fread(Data,sizeof(*Data),height*4,fp);
  1026.     fread(Mask,sizeof(*Mask),height,fp);
  1027. }
  1028.  
  1029.  
  1030. int    ColourIncarnation::TouchDraw(short x, short y, long *Store)
  1031. { return 0; }
  1032.  
  1033. void    ColourIncarnation::Draw(short x, short y, long *Store)
  1034. {
  1035.     x-=HotX;
  1036.     y-=HotY;
  1037.     unsigned short shift = 16-(x&15);
  1038.     short LineSpacing=Pages->Current().Rez().BytesPerLine();
  1039.     long *At = (long*)(Pages->Location() + y*LineSpacing+((x>>4)<<3));
  1040. #ifdef NOASM
  1041.     unsigned short *D=Data;
  1042.     unsigned short *M=Mask;
  1043.  
  1044.     unsigned long m1,m2,d1,d2,t1,t2,t3,t4;
  1045.  
  1046.     *(Store++)=(long)At;
  1047.     *(Store++)=(long)height-1;
  1048.     for (int h=0; h<height; h++) {
  1049.         t1=~(((long)*(M++)) << shift);
  1050.         m1=(t1 & 0xffff0000) | ((t1 & 0xffff0000) >> 16);
  1051.         m2=((t1 & 0x0000ffff) << 16) | (t1 & 0x0000ffff);
  1052.  
  1053.         *(Store++)=*At;
  1054.         *(Store++)=At[1];
  1055.         *(Store++)=At[2];
  1056.         *(Store++)=At[3];
  1057.  
  1058.         t1=((long)*(D++)) << shift;
  1059.         t2=((long)*(D++)) << shift;
  1060.         t3=((long)*(D++)) << shift;
  1061.         t4=((long)*(D++)) << shift;
  1062.         d1=(t1 & 0xffff0000) | ((t2 & 0xffff0000) >> 16);
  1063.         d2=((t1 & 0x0000ffff) << 16) | (t2 & 0x0000ffff);
  1064.         At[0]=(At[0] & m1) | d1;
  1065.         At[2]=(At[2] & m2) | d2;
  1066.         d1=(t3 & 0xffff0000) | ((t4 & 0xffff0000) >> 16);
  1067.         d2=((t3 & 0x0000ffff) << 16) | (t4 & 0x0000ffff);
  1068.         At[1]=(At[1] & m1) | d1;
  1069.         At[3]=(At[3] & m2) | d2;
  1070.  
  1071.         At=(long*)((long)At+LineSpacing);
  1072.     }
  1073. #else
  1074.     asm("
  1075.     movel    %4,%2@+        | Save output address
  1076.     subl    #1,%5
  1077.     movel    %5,%2@+        | Save Height-1
  1078. 0:
  1079. |    Save scanline:
  1080.     movel    %4@,%2@+
  1081.     movel    %4@(4),%2@+
  1082.     movel    %4@(8),%2@+
  1083.     movel    %4@(12),%2@+
  1084.  
  1085. |    Get mask
  1086.     clrl    d1
  1087.     movew    %1@+,d1
  1088.     asll    %3,d1
  1089.     notl    d1
  1090.  
  1091. |    Draw scanline:  Word 1
  1092.     clrl    d0
  1093.     movew    %0@+,d0
  1094.     asll    %3,d0
  1095.     movew    %4@,d4
  1096.     swap    d4
  1097.     movew    %4@(8),d4
  1098.     andl    d1,d4
  1099.     orl    d0,d4
  1100.     movew    d4,%4@(8)
  1101.     swap    d4
  1102.     movew    d4,%4@+
  1103.  
  1104. |    Draw scanline:  Word 2
  1105.     clrl    d0
  1106.     movew    %0@+,d0
  1107.     asll    %3,d0
  1108.     movew    %4@,d4
  1109.     swap    d4
  1110.     movew    %4@(8),d4
  1111.     andl    d1,d4
  1112.     orl    d0,d4
  1113.     movew    d4,%4@(8)
  1114.     swap    d4
  1115.     movew    d4,%4@+
  1116.  
  1117. |    Draw scanline:  Word 3
  1118.     clrl    d0
  1119.     movew    %0@+,d0
  1120.     asll    %3,d0
  1121.     movew    %4@,d4
  1122.     swap    d4
  1123.     movew    %4@(8),d4
  1124.     andl    d1,d4
  1125.     orl    d0,d4
  1126.     movew    d4,%4@(8)
  1127.     swap    d4
  1128.     movew    d4,%4@+
  1129.  
  1130. |    Draw scanline:  Word 4
  1131.     clrl    d0
  1132.     movew    %0@+,d0
  1133.     asll    %3,d0
  1134.     movew    %4@,d4
  1135.     swap    d4
  1136.     movew    %4@(8),d4
  1137.     andl    d1,d4
  1138.     orl    d0,d4
  1139.     movew    d4,%4@(8)
  1140.     swap    d4
  1141.     movew    d4,%4@+
  1142.  
  1143.     addl    %6,%4        | next line on screen
  1144.     subl    #8,%4
  1145.  
  1146.     dbra    %5,0b
  1147.  
  1148. " :
  1149.   :    "a" (Data),
  1150.     "a" (Mask),
  1151.     "a" (Store),
  1152.     "d" (shift),
  1153.     "a" (At),
  1154.     "d" ((long)height),
  1155.     "d" ((long)LineSpacing)
  1156.  
  1157.   :    "d0", "d1", "d4"
  1158. );
  1159. #endif
  1160. }
  1161.  
  1162. void    SimpleWipe(long *Store)
  1163. {
  1164.     short LineSpacing=Pages->Current().Rez().BytesPerLine();
  1165. #ifdef NOASM
  1166.     if (*Store) {
  1167.         long *At = (long*) *Store;
  1168.         *(Store++) = 0;
  1169.  
  1170.         for (int h=1+*(Store++); h; h--) {
  1171.             *At=*(Store++);
  1172.             At[1]=*(Store++);
  1173.             At[2]=*(Store++);
  1174.             At[3]=*(Store++);
  1175.             At=(long*)((long)At+LineSpacing);
  1176.         }
  1177.     }
  1178. #else
  1179.     asm("
  1180.     movel    %0@,d0        | Since moves to address regs don't change Z flag
  1181.     beq    1f
  1182.     movel    d0,a0
  1183.     clrl    %0@+
  1184.     movel    %0@+,d0
  1185.     subl    #12,%1
  1186. 0:
  1187.     movel    %0@+,a0@+
  1188.     movel    %0@+,a0@+
  1189.     movel    %0@+,a0@+
  1190.     movel    %0@+,a0@
  1191.     addl    %1,a0        | next line on screen
  1192.     dbra    d0,0b
  1193. 1:
  1194. " :
  1195.   :    "a" (Store),
  1196.     "d" ((long)LineSpacing)
  1197.  
  1198.   :    "d0", "a0"
  1199. );
  1200. #endif
  1201. }
  1202.  
  1203. void    ColourIncarnation::Wipe(long *Store)
  1204. {
  1205.     SimpleWipe(Store);
  1206. }
  1207.  
  1208. void    ColourIncarnation::GetImage(Screen& S, int x, int y)
  1209. {
  1210.     short LineSpacing=S.Rez().BytesPerLine();
  1211.     unsigned short *At=(unsigned short*)(S.Location()+y*LineSpacing+x/16*8);
  1212.     unsigned short or=0,*D,*M;
  1213.  
  1214.     D=Data;
  1215.     M=Mask;
  1216.     for (int h=0; h<height; h++) {
  1217.         *D++=At[0];
  1218.         *D++=At[1];
  1219.         *D++=At[2];
  1220.         *D++=At[3];
  1221.         *M=At[0]|At[1]|At[2]|At[3];
  1222.         or|=*M++;
  1223.         At=(unsigned short*)((long)At+LineSpacing);
  1224.     }
  1225.     width=LeftBits(or);
  1226. }
  1227.  
  1228.  
  1229.  
  1230. PreshiftedColourIncarnation::PreshiftedColourIncarnation(int h)
  1231.     : Incarnation(h,h*4+2)
  1232. {
  1233.     int s;
  1234.  
  1235.     for (s=0; s<16; s++) Data[s]=new unsigned short[height*4*2];
  1236.     for (s=0; s<16; s++) Mask[s]=new unsigned short[height*2];
  1237. }
  1238.  
  1239. PreshiftedColourIncarnation::~PreshiftedColourIncarnation()
  1240. {
  1241.     int s;
  1242.  
  1243.     for (s=0; s<16; s++) delete Data[s];
  1244.     for (s=0; s<16; s++) delete Mask[s];
  1245. }
  1246.  
  1247. int    PreshiftedColourIncarnation::fput(FILE *fp)
  1248. {
  1249.     short tag=5;
  1250.     fwrite(&tag,sizeof(tag),1,fp);
  1251.     Incarnation::fput(fp);
  1252.     fwrite(Data[0],sizeof(*Data[0]),height*4*2,fp);
  1253.     return fwrite(Mask[0],sizeof(*Mask[0]),height*2,fp)==height*2;
  1254. }
  1255.  
  1256. PreshiftedColourIncarnation::PreshiftedColourIncarnation(FILE *fp) :
  1257.     Incarnation(fp)
  1258. {
  1259.     int s;
  1260.  
  1261.     for (s=0; s<16; s++) Data[s]=new unsigned short[height*4*2];
  1262.     for (s=0; s<16; s++) Mask[s]=new unsigned short[height*2];
  1263.  
  1264.     Backing=height*4+2;
  1265.  
  1266.     fread(Data[0],sizeof(*Data[0]),height*4*2,fp);
  1267.     fread(Mask[0],sizeof(*Mask[0]),height*2,fp);
  1268.  
  1269.     unsigned short *D,*M,*SD,*SM;
  1270.     int h;
  1271.  
  1272.     // Invert mask (easier to shift)
  1273.     M=Mask[0];
  1274.     for (h=0; h<height; h++) {
  1275.         M[h*2]=~M[h*2];
  1276.         M[h*2+1]=~0;
  1277.     }
  1278.  
  1279.     // BELOW COPIED FROM GetImage
  1280.     unsigned long t;
  1281.  
  1282.     for (s=1; s<16; s++) {
  1283.         D=Data[0];
  1284.         M=Mask[0];
  1285.  
  1286.         SD=Data[s];
  1287.         SM=Mask[s];
  1288.  
  1289.         for (int h=0; h<height; h++) {
  1290.             for (int bp=0; bp<4; bp++) {
  1291.                 t=(long)D[bp] << (16-s);
  1292.                 SD[bp]=t>>16;
  1293.                 SD[bp+4]=t&0xffff;
  1294.             }
  1295.             SD+=8;
  1296.             D+=8;
  1297.  
  1298.             t=((unsigned long)*M++ << (16-s));
  1299.             M++;
  1300.             *SM++=~(t>>16);
  1301.             *SM++=~(t&0xffff);
  1302.         }
  1303.     }
  1304.  
  1305.     M=Mask[0];
  1306.     for (h=0; h<height; h++) {
  1307.         M[h*2]=~M[h*2];
  1308.         M[h*2+1]=~0;
  1309.     }
  1310.     // ABOVE COPIED FROM GetImage
  1311. }
  1312.  
  1313.  
  1314. int    PreshiftedColourIncarnation::TouchDraw(short x, short y, long *Store)
  1315. { return 0; }
  1316.  
  1317. void    PreshiftedColourIncarnation::Draw(short x, short y, long *Store)
  1318. {
  1319.     x-=HotX;
  1320.     y-=HotY;
  1321.     unsigned short shift = x&15;
  1322.     short LineSpacing=Pages->Current().Rez().BytesPerLine();
  1323.     long *At = (long*)(Pages->Location() + y*LineSpacing+((x>>4)<<3));
  1324. #ifdef NOASM
  1325.     unsigned short *D=Data[shift];
  1326.     unsigned short *M=Mask[shift];
  1327.  
  1328.     unsigned long m;
  1329.  
  1330.     *(Store++)=(long)At;
  1331.     *(Store++)=(long)height-1;
  1332.     for (int h=0; h<height; h++) {
  1333.         m=*(M++);
  1334.  
  1335.         *(Store++)=At[0];
  1336.         *(Store++)=At[1];
  1337.         *(Store++)=At[2];
  1338.         *(Store++)=At[3];
  1339.  
  1340.         At[0]=At[0] & m | *(D++);
  1341.         At[1]=At[1] & m | *(D++);
  1342.         At[2]=At[2] & m | *(D++);
  1343.         At[3]=At[3] & m | *(D++);
  1344.  
  1345.         At=(long*)((long)At+LineSpacing);
  1346.     }
  1347. #else
  1348.     asm("
  1349.     movel    %2,%3@+        | Save output address
  1350.     subl    #1,%4
  1351.     movel    %4,%3@+        | Save Height-1
  1352.     subl    #12,%5
  1353. 0:
  1354. |    Get mask    HH in d3, LL in d1
  1355.     movel    %0@+,d1
  1356.     movel    d1,d3
  1357.     swap    d1
  1358.     movew    d1,d0
  1359.     movew    d3,d1
  1360.     movew    d0,d3
  1361.  
  1362. |:    First word, bitplanes 0 & 1
  1363.     movel    %1@+,d0
  1364.     movel    %2@,d4
  1365.     movel    d4,%3@+
  1366.     andl    d3,d4
  1367.     orl    d0,d4
  1368.     movel    d4,%2@+
  1369.  
  1370. |:    First word, bitplanes 2 & 3
  1371.     movel    %1@+,d0
  1372.     movel    %2@,d4
  1373.     movel    d4,%3@+
  1374.     andl    d3,d4
  1375.     orl    d0,d4
  1376.     movel    d4,%2@+
  1377.  
  1378. |:    Second word (second mask), bitplanes 0 & 1
  1379.     movel    %1@+,d0
  1380.     movel    %2@,d4
  1381.     movel    d4,%3@+
  1382.     andl    d1,d4
  1383.     orl    d0,d4
  1384.     movel    d4,%2@+
  1385.  
  1386. |:    Second word (second mask), bitplanes 2 & 3
  1387.     movel    %1@+,d0
  1388.     movel    %2@,d4
  1389.     movel    d4,%3@+
  1390.     andl    d1,d4
  1391.     orl    d0,d4
  1392.     movel    d4,%2@
  1393.  
  1394.     addl    %5,%2    | next line on screen
  1395.  
  1396.     dbra    %4,0b
  1397. " :
  1398.   :    "a" (Mask[shift]),
  1399.     "a" (Data[shift]),
  1400.     "a" (At),
  1401.     "a" (Store),
  1402.     "d" (height),
  1403.     "d" ((long)LineSpacing)
  1404.   :    "d0", "d1", "d3", "d4"
  1405. );
  1406. #endif
  1407. }
  1408.  
  1409. void    PreshiftedColourIncarnation::Wipe(long *Store)
  1410. {
  1411.     SimpleWipe(Store);
  1412. }
  1413.  
  1414.  
  1415. void    PreshiftedColourIncarnation::GetImage(Screen& S, int x, int y)
  1416. {
  1417.     short LineSpacing=S.Rez().BytesPerLine();
  1418.     unsigned short *At=(unsigned short*)(S.Location()+y*LineSpacing+x/16*8);
  1419.     unsigned short or=0,*D,*M,*SD,*SM;
  1420.     unsigned long t;
  1421.     int h,bp;
  1422.  
  1423.     D=Data[0];
  1424.     M=Mask[0];
  1425.     for (h=0; h<height; h++) {
  1426.         *D++=At[0];
  1427.         *D++=At[1];
  1428.         *D++=At[2];
  1429.         *D++=At[3];
  1430.         *D++=0;
  1431.         *D++=0;
  1432.         *D++=0;
  1433.         *D++=0;
  1434.         *M=(At[0]|At[1]|At[2]|At[3]);
  1435.         or|=*M++;
  1436.         *M++=0;
  1437.         At=(unsigned short*)((long)At+LineSpacing);
  1438.     }
  1439.     width=LeftBits(or);
  1440.  
  1441.     for (int s=1; s<16; s++) {
  1442.         D=Data[0];
  1443.         M=Mask[0];
  1444.  
  1445.         SD=Data[s];
  1446.         SM=Mask[s];
  1447.  
  1448.         for (h=0; h<height; h++) {
  1449.             for (bp=0; bp<4; bp++) {
  1450.                 t=(long)D[bp] << (16-s);
  1451.                 SD[bp]=t>>16;
  1452.                 SD[bp+4]=t&0xffff;
  1453.             }
  1454.             SD+=8;
  1455.             D+=8;
  1456.  
  1457.             t=((unsigned long)*M++ << (16-s));
  1458.             M++;
  1459.             *SM++=~(t>>16);
  1460.             *SM++=~(t&0xffff);
  1461.         }
  1462.     }
  1463.  
  1464.     M=Mask[0];
  1465.     for (h=0; h<height; h++) {
  1466.         M[h*2]=~M[h*2];
  1467.         M[h*2+1]=~0;
  1468.     }
  1469. }
  1470.  
  1471.  
  1472.  
  1473. TrueColourIncarnation::TrueColourIncarnation(int w, int h) :
  1474.     Incarnation(h,1),
  1475.     Data(0),
  1476.     DataLength(0)
  1477. {
  1478.     width=w;
  1479. }
  1480.  
  1481. TrueColourIncarnation::~TrueColourIncarnation()
  1482. {
  1483.     if (Data) delete Data;
  1484. }
  1485.  
  1486. int    TrueColourIncarnation::fput(FILE *fp)
  1487. {
  1488.     short tag=6;
  1489.     fwrite(&tag,sizeof(tag),1,fp);
  1490.     Incarnation::fput(fp);
  1491.     fwrite(&Backing,sizeof(Backing),1,fp);
  1492.     fwrite(&DataLength,sizeof(DataLength),1,fp);
  1493.     return fwrite(Data,sizeof(Data[0]),DataLength,fp)==DataLength;
  1494. }
  1495.  
  1496. TrueColourIncarnation::TrueColourIncarnation(FILE *fp) :
  1497.     Incarnation(fp)
  1498. {
  1499.     fread(&Backing,sizeof(Backing),1,fp);
  1500.     fread(&DataLength,sizeof(DataLength),1,fp);
  1501.     fread(Data,sizeof(Data[0]),DataLength,fp);
  1502. }
  1503.  
  1504.  
  1505. int    TrueColourIncarnation::TouchDraw(short x, short y, long *Store)
  1506. {
  1507.     // Oh, come on, this is easy to implement!
  1508.     return 0;
  1509. }
  1510.  
  1511. void    TrueColourIncarnation::Draw(short x, short y, long *Store)
  1512. {
  1513.     x-=HotX;
  1514.     y-=HotY;
  1515.     short *At = (short*)(Pages->Location()) + x + y*Pages->Current().Rez().BytesPerLine()/sizeof(short);
  1516.  
  1517. // Automatically generated by gentcd
  1518. #include "../src/tcd.icc"
  1519. }
  1520.  
  1521. void    TrueColourIncarnation::Wipe(long *Store)
  1522. {
  1523. // Automatically generated by gentcd
  1524. #include "../src/tcw.icc"
  1525. }
  1526.  
  1527.  
  1528. // TrueColour incarnations are drawn using a series of "commands"
  1529. // from the Data.  The commands are:
  1530. //
  1531. //    0    Quit
  1532. //    1..22    n sequential pixels (n pos value^n)
  1533. //
  1534. //    24    5x1-pixel (24 value^5 pos^5)
  1535. //    25    5x2-pixel (25 value^10 pos^5)
  1536. //    26    3x2;2x4-pixel (26 value^14 pos^5)
  1537. //
  1538. //    32    5x1-pixel 'AND'
  1539. //    33    5x2-pixel 'AND'
  1540. //    34    3x2;2x4-pixel 'AND'
  1541. //
  1542. //    40    5x1-pixel 'ADD'
  1543. //    41    5x2-pixel 'ADD'
  1544. //    42    3x2;2x4-pixel 'ADD'
  1545. //
  1546. //    48    5x1-pixel 'OR'
  1547. //    49    5x2-pixel 'OR'
  1548. //    50    3x2;2x4-pixel 'OR'
  1549.  
  1550.  
  1551. #define PUT5 24
  1552. #define PUT10 25
  1553. #define PUT14 26
  1554.  
  1555. void TrueColourIncarnation::GetImage(Screen& S, int x, int y)
  1556. {
  1557.     short LineSpacing=S.Rez().BytesPerLine()/sizeof(short);
  1558.     unsigned short *At=(unsigned short*)(S.Location())+y*LineSpacing+x;
  1559.  
  1560.     if (Data) delete Data;
  1561.  
  1562. // Limited implementation:  two-pass, n-pixel commands only...
  1563.  
  1564.     int cmdcount=0;
  1565.     int bckcount=0;
  1566.     for (int final=0; final<=1; final++) {
  1567.         unsigned short* d=0;
  1568.         if (final) {
  1569.             Data=new unsigned short[cmdcount];
  1570.             Backing=bckcount;
  1571.             d=Data;
  1572.         }
  1573.         for (int j=0; j<height; j++) {
  1574.             for (int i=0; i<width; i++) {
  1575.                 int n=0;
  1576.                 while (n<22 && i+n<width && At[j*LineSpacing+i+n]) n++;
  1577.                 if (n) {
  1578.                     // n-PIXEL command...
  1579.  
  1580.                     if (final) {
  1581.                         *(d++)=n;
  1582.                         *((long*)d)=(j*LineSpacing+i)*sizeof(short);
  1583.                         d+=2;
  1584.                         for (int N=0; N<(n); N++)
  1585.                             *(d++)=At[j*LineSpacing+i+N];
  1586.                     } else {
  1587.                         cmdcount+=1+2+n;
  1588.                         bckcount+=n;
  1589.                     }
  1590.                     i+=n-1;
  1591.                 }
  1592.             }
  1593.         }
  1594.  
  1595.         // QUIT command...
  1596.         if (final) {
  1597.             *(d++)=0;
  1598.         } else {
  1599.             cmdcount++;
  1600.             bckcount+=2; // includes initial pos storage
  1601.         }
  1602.     }
  1603. }
  1604.